﻿using System;
using System.Windows.Forms;
using LevelEditor.View;
using WeifenLuo.WinFormsUI.Docking;

namespace LevelEditor.Forms
{
    public partial class HistoryForm : DockContent
    {
        #region Fields

        bool DontCallHistoryManager = false;

        #endregion

        #region Properties

        /// <summary>
        /// Get the index of the selected item of the list box
        /// </summary>
        public int SelectedIndex
        {
            get { return historyListBox.SelectedIndex; }
        }

        #endregion

        #region Constructors

        public HistoryForm(HistoryManager historyManager)
        {
            InitializeComponent();
            if (historyManager != null)
            {
                historyManager.AddAction += new HistoryManager.AddActionEventHandler(historyManager_AddAction);
                historyManager.Changed += new HistoryManager.ChangedEventHandler(historyManager_Changed);
                historyManager.Cleared += new HistoryManager.ClearEventHandler(historyManager_Cleared);
                LoadData(historyManager);
            }
            else
                throw new NullReferenceException("History Manager is a null reference.");
        }

        #endregion

        #region Event Handlers

        public delegate void SelectedIndexChangedEventHandler(object sender, EventArgs e);
        public event SelectedIndexChangedEventHandler SelectedIndexChanged;
        protected void OnSelectedIndexChanged(EventArgs e)
        {
            if (SelectedIndexChanged != null)
                SelectedIndexChanged(this, e);
        }

        public delegate void ClearMenuItemClickedEventHandler(object sender, EventArgs e);
        public event ClearMenuItemClickedEventHandler ClearMenuItemClicked;
        protected void OnClearMenuItemClicked(EventArgs e)
        {
            if (ClearMenuItemClicked != null)
                ClearMenuItemClicked(this, e);
        }

        public delegate void UndoMenuItemClickedEventHandler(object sender, EventArgs e);
        public event UndoMenuItemClickedEventHandler UndoMenuItemClicked;
        protected void OnUndoMenuItemClicked(EventArgs e)
        {
            if (UndoMenuItemClicked != null)
                UndoMenuItemClicked(this, e);
        }

        public delegate void RedoMenuItemClickedEventHandler(object sender, EventArgs e);
        public event RedoMenuItemClickedEventHandler RedoMenuItemClicked;
        protected void OnRedoMenuItemClicked(EventArgs e)
        {
            if (RedoMenuItemClicked != null)
                RedoMenuItemClicked(this, e);
        }

        #endregion

        #region Helper Methods

        private void LoadData(HistoryManager historyManager)
        {
            UpdateList(historyManager);
            UpdateContextMenu(historyManager);
        }

        /// <summary>
        /// Updates the action list based on the History Manager
        /// </summary>
        private void UpdateList(HistoryManager historyManager)
        {
            historyListBox.Items.Clear();
            for (int i = historyManager.TimeLine.Count - 1; i >= 0; --i)
            {
                historyListBox.Items.Add(historyManager.TimeLine[i].ToString());
            }
            UpdateSelected(historyManager);
        }

        /// <summary>
        /// Updates the selected index based on the History Manager
        /// </summary>
        private void UpdateSelected(HistoryManager historyManager)
        {
            DontCallHistoryManager = true;
            historyListBox.SelectedIndex = historyListBox.Items.Count - historyManager.CurrentActionIndex - 1;
            DontCallHistoryManager = false;
            Invalidate();
        }

        /// <summary>
        /// Updates the availability of Context menu options based on the History Manager
        /// </summary>
        private void UpdateContextMenu(HistoryManager historyManager)
        {
            undoToolStripMenuItem.Enabled = true;
            redoToolStripMenuItem.Enabled = true;
            clearHistoryToolStripMenuItem.Enabled = true;
            UpdateSelected(historyManager);
            if (historyManager.TimeLine.Count == 1)
            {
                undoToolStripMenuItem.Enabled = false;
                redoToolStripMenuItem.Enabled = false;
                clearHistoryToolStripMenuItem.Enabled = false;
            }
            else
            {
                if (historyManager.CurrentActionIndex == 0)
                {
                    undoToolStripMenuItem.Enabled = false;
                }
                if (historyManager.CurrentActionIndex == historyManager.TimeLine.Count - 1)
                {
                    redoToolStripMenuItem.Enabled = false;
                }
            }
        }

        #endregion

        #region Events

        private void historyListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!DontCallHistoryManager)
            {
                OnSelectedIndexChanged(e);
            }
        }

        private void HistoryForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            Hide();
        }

        private void clearHistoryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OnClearMenuItemClicked(e);
        }

        private void undoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OnUndoMenuItemClicked(e);
        }

        private void redoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OnRedoMenuItemClicked(e);
        }

        void historyManager_Cleared(object sender, EventArgs e)
        {
            UpdateList((sender as HistoryManager));
        }

        void historyManager_Changed(object sender, EventArgs e)
        {
            UpdateContextMenu((sender as HistoryManager));
        }

        void historyManager_AddAction(object sender, EventArgs e)
        {
            UpdateList((sender as HistoryManager));
        }

        #endregion

    }
}
